<template>
  <div :id="props.id" class="video-player-context">
    <canvas
      :ref="(el) => setItemRef(el, `download-${props.id}`)"
      :id="`download-${props.id}`"
      class="kind-stream-canvas video-player-canvas"
      kind-channel-id="0"
      width="1920"
      height="1080"
      style="visibility: hidden"
    ></canvas>
    <canvas
      :ref="(el) => setItemRef(el, `downloadIvs-${props.id}`)"
      :id="`downloadIvs-${props.id}`"
      class="kind-stream-canvas video-player-canvas"
      width="1920"
      height="1080"
      style="visibility: hidden"
    ></canvas>
    <canvas
      :ref="(el) => setItemRef(el, `talk-${props.id}`)"
      :id="`talk-${props.id}`"
      class="kind-stream-canvas video-player-canvas"
      kind-channel-id="0"
      width="1920"
      height="1080"
      style="visibility: hidden"
    ></canvas>
    <canvas
      :ref="(el) => setItemRef(el, `talkIvs-${props.id}`)"
      :id="`talkIvs-${props.id}`"
      class="kind-stream-canvas video-player-canvas"
      width="1920"
      height="1080"
      style="visibility: hidden"
    ></canvas>
    <canvas
      :ref="(el) => setItemRef(el, `can-${props.id}`)"
      :id="`can-${props.id}`"
      class="kind-stream-canvas video-player-canvas"
      kind-channel-id="0"
      width="1920"
      height="1080"
      :style="{ visibility: isPlay ? 'visible' : 'hidden' }"
    ></canvas>
    <canvas
      :ref="(el) => setItemRef(el, `ivsCan-${props.id}`)"
      :id="`ivsCan-${props.id}`"
      class="kind-stream-canvas video-player-canvas"
      width="1920"
      height="1080"
      :style="{ visibility: isPlay ? 'visible' : 'hidden' }"
    ></canvas>
    <video
      :ref="(el) => setItemRef(el, `video-${props.id}`)"
      :id="`video-${props.id}`"
      class="kind-stream-canvas"
      kind-channel-id="0"
      width="1920"
      height="1080"
      :style="{ visibility: isPlay ? 'visible' : 'hidden' }"
    ></video>
    <video
      :ref="(el) => setItemRef(el, `download-video-${props.id}`)"
      :id="`download-video-${props.id}`"
      class="kind-stream-canvas"
      kind-channel-id="0"
      width="1920"
      height="1080"
      style="visibility: hidden"
    ></video>
    <video
      :ref="(el) => setItemRef(el, `talk-video-${props.id}`)"
      :id="`talk-video-${props.id}`"
      class="kind-stream-canvas"
      kind-channel-id="0"
      width="1920"
      height="1080"
      style="visibility: hidden"
    ></video>
    <img :src="loading" v-if="isLoading" />
    <div class="diy-device-id" v-show="openDiyDevId">
      <a-form :model="formState" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
        <a-form-item label="设备秘钥">
          <a-input
            v-model:value="formState.strDeviceID"
            type="password"
            placeholder="请输入设备秘钥"
          />
        </a-form-item>
        <a-form-item :wrapper-col="{ span: 18, offset: 4 }">
          <a-button type="primary" @click="onSubmit">确定</a-button>
        </a-form-item>
      </a-form>
    </div>
  </div>
</template>
<script setup name="VideoPlayer">
  import {
    Form as AForm,
    FormItem as AFormItem,
    Button as AButton,
    Input as AInput,
  } from 'ant-design-vue'
  import PlayerControl from './playerWasm/PlaySDKInterface.js'
  import LoadingImg from './img/loading.png'
  import { checkBrowser } from './playerWasm/public.js'

  const props = defineProps({
    id: {
      type: String,
      default: Date.now().toString(),
    },
    rtspURL: {
      type: String,
      required: true,
    },
    // 对讲url
    audioURL: {
      type: String,
    },
    // 录像下载url
    downloadURL: {
      type: String,
    },
    channelId: {
      type: String,
      default: '0',
    },
    // 主辅码流  0 主码流 1 辅码流
    bitStream: {
      type: Number,
      default: 0,
    },
    // 是否是直播
    isLive: {
      type: Boolean,
      default: true,
    },
    // 偏移量
    npt: {
      type: String || Number,
      default: 0,
    },
    // 0:非加密 1:mikey 2:0x95 3:0xB5
    encryptMode: {
      type: Number,
      default: 0,
    },
    deviceId: {
      type: String,
      default: '',
    },
    playTokenKey: {
      type: String,
      default: '',
    },
    playToken: {
      type: String,
      default: '',
    },
    // 全景角度，默认关闭全景
    panoAR: {
      type: Number,
      default: 0,
    },
    userName: {
      type: String,
      default: 'admin',
    },
    password: {
      type: String,
      default: 'admin123',
    },
    // 三维点云，默认关闭三维点云
    open3DPoint: {
      type: Number,
      default: 0,
    },
    // 是否是标准流打包 true rtsp标准打包;false 大华帧打包
    isSandardPack: {
      type: Boolean,
      default: true,
    },
  })

  const emit = defineEmits([
    'downloadProgressUpdate',
    'playProgressUpdate',
    'downloadComplete',
    'playError',
    'talkError',
    'downloadError',
    'recordError',
    'update:rtspURL',
    'talkStart',
    'playFileOver',
  ])

  const isLoading = ref(false)
  const loading = LoadingImg
  const isPlay = ref(false)
  const formState = reactive({
    strDeviceID: '',
  })
  let isPrivateProtocol = false

  watch(
    () => props.rtspURL,
    (val) => {
      isPrivateProtocol = val.includes('rtsp://') ? false : true
    },
  )
  watch(
    () => props.audioURL,
    (val) => {
      isPrivateProtocol = val.includes('rtsp://') ? false : true
    },
  )
  watch(
    () => props.downloadURL,
    (val) => {
      isPrivateProtocol = val.includes('rtsp://') ? false : true
    },
  )

  watch(
    () => props.panoAR,
    (val) => {
      player && player.SetPanoAR(val)
    },
  )
  // websocket连接地址
  const wsURL = computed(() => {
    const { protocol } = location
    const [wsIP] = props.rtspURL.replace('rtsp://', '').split('/')
    const ws = `${protocol === 'http:' && !props.rtspURL.includes('8556') ? 'ws' : 'wss'}://${wsIP}`
    return !isPrivateProtocol ? `${ws}` : `${ws}`
  })

  // 对讲websocket连接地址
  const audioWsURL = computed(() => {
    const { protocol } = location
    const [wsIP] = props.audioURL.replace('rtsp://', '').split('/')
    const ws = `${
      protocol === 'http:' && !props.audioURL.includes('8556') ? 'ws' : 'wss'
    }://${wsIP}`
    return !isPrivateProtocol ? ws : `${ws}`
  })

  // websocket连接地址
  const downloadWsURL = computed(() => {
    const { protocol } = location
    const [wsIP] = props.downloadURL.replace('rtsp://', '').split('/')
    const ws = `${
      protocol === 'http:' && !props.downloadURL.includes('8556') ? 'ws' : 'wss'
    }://${wsIP}`
    return !isPrivateProtocol ? ws : `${ws}`
  })

  // rtsp流地址
  const rtspStream = computed(() => {
    let rtsp = props.rtspURL.includes('rtsp://') ? props.rtspURL : `rtsp://${props.rtspURL}`
    rtsp = !isPrivateProtocol
      ? props.isLive
        ? rtsp
        : rtsp.replace(
            /&beginTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}&endTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/,
            '',
          )
      : props.isLive
      ? `/live/realmonitor.xav?channel=${props.channelId}&subtype=${props.bitStream}`
      : `/vod/playback.xav?channel=${props.channelId}&subtype=${props.bitStream}`
    if (isPrivateProtocol) {
      const timeRangeArr =
        /&beginTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}&endTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.exec(
          props.rtspURL,
        )
      if (timeRangeArr) {
        const timeRange = timeRangeArr[0].replace(
          /(&beginTime=)(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(&endTime=)(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/,
          '&starttime=$2_$3_$4_$5_$6_$7&endtime_$9_$10_$11_$12_$13',
        )
        rtsp += timeRange
      }
    }
    // if (!!props.encryptMode) {
    //   rtsp += '&encrypt=' + props.encryptMode
    // }
    return rtsp
  })

  // 录像下载流地址
  const downloadStream = computed(() => {
    let rtsp = props.downloadURL.includes('rtsp://')
      ? props.downloadURL
      : `rtsp://${props.downloadURL}`
    rtsp = !isPrivateProtocol
      ? props.isLive
        ? rtsp
        : rtsp.replace(
            /&beginTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}&endTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/,
            '',
          )
      : props.isLive
      ? `/live/realmonitor.xav?channel=${props.channelId}&subtype=${props.bitStream}`
      : `/vod/playback.xav?channel=${props.channelId}&subtype=${props.bitStream}`
    if (isPrivateProtocol) {
      const timeRangeArr =
        /&beginTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}&endTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.exec(
          props.downloadURL,
        )
      if (timeRangeArr) {
        const timeRange = timeRangeArr[0].replace(
          /(&beginTime=)(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(&endTime=)(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/,
          '&starttime=$2_$3_$4_$5_$6_$7&endtime_$9_$10_$11_$12_$13',
        )
        rtsp += timeRange
      }
    }
    // if (!!props.encryptMode) {
    //   rtsp += '&encrypt=' + props.encryptMode
    // }
    return rtsp
  })

  // 对讲流地址
  const audioStream = computed(() => {
    let audioURL = props.audioURL.includes('rtsp://') ? props.audioURL : `rtsp://${props.audioURL}`
    audioURL = !isPrivateProtocol
      ? audioURL
      : `/live/talk.xav?channel=${props.channelId}&subtype=${props.bitStream}`
    // if (!!props.encryptMode) {
    //   audioURL += '&encrypt=' + props.encryptMode
    // }
    return audioURL
  })

  // 私有流发送信令试携带的sourceId
  const sourceId = computed(() => {
    let id = props.rtspURL.replace('rtsp://', '').split('/')[1]
    if (isPrivateProtocol) {
      return id.replace(
        /&beginTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}&endTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/,
        '',
      )
    }
    return id
  })

  const audioSourceId = computed(() => {
    return props.audioURL.replace('rtsp://', '').split('/')[1]
  })

  const downloadSourceId = computed(() => {
    let id = props.downloadURL.replace('rtsp://', '').split('/')[1]
    if (isPrivateProtocol) {
      return id.replace(
        /&beginTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}&endTime=\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/,
        '',
      )
    }
    return id
  })

  let player = null
  let playerPort = null
  let playerHandle = null
  let volume = 1
  let talkVolume = 1
  let optStatus = ''
  let timer = null
  const openDiyDevId = ref(false)
  const playRefs = {}
  const setItemRef = (el, key) => {
    if (el) {
      playRefs[key] = el
    }
  }
  /**
   * @method play 播放
   */
  const play = (vol) => {
    if (!props.rtspURL) return
    if (player) {
      player.close()
    }
    const initParam = {
      canvasElem: playRefs[`can-${props.id}`],
      videoElem: playRefs[`video-${props.id}`],
      ivsCanvasElem: playRefs[`ivsCan-${props.id}`],
      bPlayBack: props.isLive === false,
      strDecodeFilePath: 'WasmLib/SingleThread',
    }
    const urlParam = {
      strRtspvUri: wsURL.value,
      strRtspvUrl: rtspStream.value,
      strPlayToken: props.playToken,
      strPlayTokenKey: props.playTokenKey,
      strDeviceID: props.deviceId,
      strSourceId: isPrivateProtocol ? sourceId.value : '',
      strUserName: props.userName,
      strPassWord: props.password,
      bTalkService: false,
      nRange: props.npt,
      nShortTimeout: 3,
      nRtspResponseTimeout: 8,
      bStandardPack: props.isSandardPack,
    }
    if (vol || vol === 0) {
      volume = vol
    }
    const { bSupportMultiThread } = checkBrowser()

    player = new PlayerControl(bSupportMultiThread)
    isLoading.value = true
    player.SetCallBack('StreamPlayOver', () => {
      if (player) {
        // 异步执行，防止死锁
        setTimeout(close, 1)
        emit('playFileOver')
      }
    })
    player.SetCallBack('PlayStart', () => {
      isPlay.value = true
      if (isLoading.value) isLoading.value = false
    })
    player.SetCallBack('CaptureChanged', (blob) => {
      emit('captureCallback', blob)
    })
    player.SetCallBack('VideoFrameInfo', (e) => {
      if (e.timeStamp) {
        clearTimeout(timer)
        timer = setTimeout(() => {
          emit('playError', {
            errorCode: '409',
            errMsg: 'Rtsp Not Response.',
          })
        }, 10000)
      }
      const msg = {
        frameRate: e.nFrameRate,
        time: e.timeStamp,
        utcTime: e.utcTimeStamp,
      }
      emit('playProgressUpdate', msg)
    })
    player.SetCallBack('DecodeStart', (e) => {
      if (e.decodeMode === 'video') {
        playRefs[`can-${props.id}`].style.display = 'none'
        playRefs[`video-${props.id}`].style.display = ''
      } else {
        playRefs[`can-${props.id}`].style.display = ''
        playRefs[`video-${props.id}`].style.display = 'none'
      }
    })
    player.SetCallBack('Error', (e) => {
      isPlay.value = false
      emit('playError', e)
    })
    player.SetCallBack('CapturePicDataCallBack', (blob) => {
      capturePicDataCallBack && capturePicDataCallBack(blob)
    })
    player.SetCallBack('GetPlayPort', (port) => {
      playerPort = port
    })
    player.SetCallBack('GetOriginalKey', ({ nRet, outKey }) => {
      if (nRet == 1) {
        urlParam.strDeviceID = outKey
        playerHandle = player.StartPullStream(JSON.parse(JSON.stringify(urlParam)))
      } else {
        optStatus = 'play'
        openDiyDevId.value = true
      }
    })
    player.Init(initParam)
    player.SetSoundState(true)
    player.SetVolume(volume)
    player.Set3DPoint(props.open3DPoint)
    if (!!props.encryptMode) {
      player.GetOriginalKey({
        strPlayToken: props.playToken,
        strPlayTokenKey: props.playTokenKey,
        strDeviceID: props.deviceId,
      })
    } else {
      playerHandle = player.StartPullStream(JSON.parse(JSON.stringify(urlParam)))
    }
  }

  /**
   * @method openIVS 开启智能帧
   */
  const openIVS = () => {
    player && player.OpenIVS()
  }

  /**
   * @method closeIVS 关闭智能帧
   */
  const closeIVS = () => {
    player && player.CloseIVS()
  }

  let talkPlayer = null
  let talkHandle = null
  let talkPort = null
  /**
   * @method talk 对讲
   */
  const talk = (vol) => {
    const initParam = {
      canvasElem: playRefs[`talk-${props.id}`],
      videoElem: playRefs[`talk-video-${props.id}`],
      ivsCanvasElem: playRefs[`talkIvs-${props.id}`],
      bPlayBack: props.isLive === false,
      strDecodeFilePath: 'WasmLib/SingleThread',
    }
    const urlParam = {
      strRtspvUri: audioWsURL.value,
      strRtspvUrl: audioStream.value,
      strPlayToken: props.playToken,
      strPlayTokenKey: props.playTokenKey,
      strDeviceID: props.deviceId,
      strSourceId: isPrivateProtocol ? audioSourceId.value : '',
      strUserName: props.userName,
      strPassWord: props.password,
      bTalkService: true,
      nRange: props.npt,
      nShortTimeout: 3,
      nRtspResponseTimeout: 8,
      bStandardPack: props.isSandardPack,
    }
    if (vol || vol === 0) {
      talkVolume = vol
    }
    if (talkPlayer) {
      talkPlayer.StopTalk()
      talkPlayer.StopPullStream()
      talkPlayer.Stop()
      talkPlayer = null
    } else {
      const { bSupportMultiThread } = checkBrowser()
      talkPlayer = new PlayerControl(bSupportMultiThread)
      talkPlayer.SetCallBack('Error', (e) => {
        emit('talkError', e)
      })
      talkPlayer.SetCallBack('GetPlayPort', (port) => {
        if (!isPlay.value) talkPort = port
      })
      talkPlayer.SetCallBack('GetOriginalKey', ({ nRet, outKey }) => {
        if (nRet == 1) {
          urlParam.strDeviceID = outKey
          talkHandle = talkPlayer.StartPullStream(JSON.parse(JSON.stringify(urlParam)))
          talkPlayer.StartTalk(null, 0)
        } else {
          optStatus = 'talk'
          openDiyDevId.value = true
        }
      })
      talkPlayer.Init(initParam)
      talkPlayer.SetSoundState(true)
      talkPlayer.SetVolume(talkVolume)
      if (!!props.encryptMode) {
        talkPlayer.GetOriginalKey({
          strPlayToken: props.playToken,
          strPlayTokenKey: props.playTokenKey,
          strDeviceID: props.deviceId,
        })
      } else {
        talkHandle = talkPlayer.StartPullStream(JSON.parse(JSON.stringify(urlParam)))
        talkPlayer.StartTalk(null, 0)
      }
    }
  }

  const talkMute = () => {
    if (talkPlayer) {
      talkPlayer.StopTalk()
    }
  }

  const talkEnabled = () => {
    if (talkPlayer) {
      talkPlayer.StartTalk(null, 0)
    }
  }

  let isRecording = false
  /**
   * @method record 实时录像
   * @param { String } fileName 录像文件名称
   */
  const record = (fileName) => {
    if (!player) return
    if (!isRecording) {
      isRecording = true
      player.StartRecord(5, 1000, fileName || Date.now() + '.mp4')
    } else {
      isRecording = false
      player.StopRecord()
    }
  }

  let downloadPlayer = null
  let downloadHandle = null
  let downloadPlayerPort = null
  let isSpeed = false
  let downloadTimer = null
  /**
   * @method download 下载
   * @param { String } fileName 下载文件名称
   */
  const download = (fileName, speed = 2) => {
    const initParam = {
      canvasElem: playRefs[`download-${props.id}`],
      videoElem: playRefs[`download-video-${props.id}`],
      ivsCanvasElem: playRefs[`downloadIvs-${props.id}`],
      bPlayBack: props.isLive === false,
      strDecodeFilePath: 'WasmLib/SingleThread',
    }
    const urlParam = {
      strRtspvUri: downloadWsURL.value,
      strRtspvUrl: downloadStream.value,
      strPlayToken: props.playToken,
      strPlayTokenKey: props.playTokenKey,
      strDeviceID: props.deviceId,
      strSourceId: isPrivateProtocol ? downloadSourceId.value : '',
      strUserName: props.userName,
      strPassWord: props.password,
      bTalkService: false,
      nRange: props.npt,
      nShortTimeout: 3,
      nRtspResponseTimeout: 8,
      bStandardPack: props.isSandardPack,
    }
    if (!downloadPlayer) {
      const { bSupportMultiThread } = checkBrowser()
      downloadPlayer = new PlayerControl(bSupportMultiThread)
      isSpeed = false
      downloadPlayer.SetCallBack('Error', (e) => {
        emit('downloadError', e)
      })
      downloadPlayer.SetCallBack('StreamPlayOver', () => {
        if (downloadPlayer) {
          downloadPlayer.StopRecord()
          emit('downloadComplete')
          downloadPlayer = null
        }
      })
      downloadPlayer.SetCallBack('Disconnect', (e) => {
        downloadPlayer.StopRecord()
        emit('downloadError', e)
        downloadPlayer = null
      })
      downloadPlayer.SetCallBack('PlayBackStreamRange', (time) => {
        emit('videoDownloadDuration', time)
      })
      downloadPlayer.SetCallBack('RecordTimeStamp', (e) => {
        if (!isSpeed && speed && e.timeStamp) {
          downloadPlayer.SetSpeed(speed)
          isSpeed = true
        }
        if (e.timeStamp) {
          clearTimeout(downloadTimer)
          downloadTimer = setTimeout(() => {
            emit('downloadError', {
              errorCode: '409',
              errMsg: 'Rtsp Not Response.',
            })
          }, 10000)
        }
        const msg = {
          size: e.size,
          time: e.timeStamp,
          utcTime: e.utcTimeStamp,
        }
        emit('downloadProgressUpdate', msg)
      })
      downloadPlayer.SetCallBack('GetPlayPort', (port) => {
        downloadPlayerPort = port
      })
      downloadPlayer.SetCallBack('GetOriginalKey', ({ nRet, outKey }) => {
        if (nRet == 1) {
          urlParam.strDeviceID = outKey
          downloadHandle = downloadPlayer.StartPullStream(JSON.parse(JSON.stringify(urlParam)))
          downloadPlayer.StartRecord(5, 1000, fileName || Date.now() + '.mp4')
        } else {
          optStatus = 'download'
          openDiyDevId.value = true
        }
      })
      downloadPlayer.Init(initParam)
      downloadPlayer.Set3DPoint(props.open3DPoint)
      if (!!props.encryptMode) {
        downloadPlayer.GetOriginalKey({
          strPlayToken: props.playToken,
          strPlayTokenKey: props.playTokenKey,
          strDeviceID: props.deviceId,
        })
      } else {
        downloadHandle = downloadPlayer.StartPullStream(JSON.parse(JSON.stringify(urlParam)))
        downloadPlayer.StartRecord(5, 1000, fileName || Date.now() + '.mp4')
      }
    } else {
      downloadPlayer.StopRecord()
      downloadPlayer.StopPullStream()
      downloadPlayer.Stop()
    }
  }

  const onSubmit = () => {
    const urlParam = {
      strRtspvUri: audioWsURL.value,
      strRtspvUrl: audioStream.value,
      strSourceId: '',
      strUserName: props.userName,
      strPassWord: props.password,
      strDeviceID: formState.strDeviceID,
      bTalkService: false,
      nRange: props.npt,
    }
    switch (optStatus) {
      case 'play':
        playerHandle = player.StartPullStream(JSON.parse(JSON.stringify(urlParam)))
      case 'talk':
        urlParam.bTalkService = true
        talkHandle = talkPlayer.StartPullStream(JSON.parse(JSON.stringify(urlParam)))
        talkPlayer.StartTalk(null, 0)
      case 'download':
        downloadHandle = downloadPlayer.StartPullStream(JSON.parse(JSON.stringify(urlParam)))
        downloadPlayer.StartRecord(5, 1000, fileName || Date.now() + '.mp4')
    }
    optStatus = ''
    openDiyDevId.value = false
  }

  /**
   * @method screenshot 截图
   */
  const screenshot = () => {
    player && player.CapturePic(`${Date.now()}.jpg`)
  }

  let capturePicDataCallBack = null
  /**
   * @method getScreenshot 获取截图数据
   */
  const getScreenshot = (callback) => {
    capturePicDataCallBack = callback
    player && player.CapturePic(null)
  }

  /**
   * @method close 视频关闭
   */
  const close = () => {
    if (talkPlayer) {
      talkPlayer.StopTalk()
      talkPlayer.StopPullStream()
      talkPlayer.Stop()
      talkPlayer = null
    }
    optStatus = ''
    clearTimeout(timer)
    player && player.StopPullStream()
    player && player.Stop()
    isPlay.value = false
    isLoading.value = false
    player = null
    emit('update:rtspURL', '')
  }

  /**
   * @method setAudioVolume 声音设置
   */
  const setAudioVolume = (val) => {
    if (!window.webAudioPlayer) {
      let intervalId = setInterval(() => {
        if (window.webAudioPlayer) {
          window.webAudioPlayer.resume()
          clearInterval(intervalId)
        }
      })
    } else {
      window.webAudioPlayer.resume()
    }
    volume = val
    player && player.SetVolume(val)
  }

  /**
   * @method setTalkVolume 对讲声音设置
   */
  const setTalkVolume = (val) => {
    if (!window.webAudioPlayer) {
      let intervalId = setInterval(() => {
        if (window.webAudioPlayer) {
          window.webAudioPlayer.resume()
          clearInterval(intervalId)
        }
      })
    } else {
      window.webAudioPlayer.resume()
    }
    talkVolume = val
    talkPlayer && talkPlayer.SetVolume(val)
  }

  /**
   * @method pause 暂停拉流
   */
  const pause = () => {
    player && player.Pause(1)
    clearTimeout(timer)
  }

  /**
   * @method start 继续拉流
   */
  const start = () => {
    player && player.Pause(0)
  }

  /**
   * @method downloadPause 暂停下载
   */
  const downloadPause = () => {
    downloadPlayer && downloadPlayer.Pause(1)
    clearTimeout(downloadTimer)
  }

  /**
   * @method downloadStart 继续下载
   */
  const downloadStart = () => {
    downloadPlayer && downloadPlayer.Pause(0)
  }

  /**
   * @method downloadClose 关闭下载
   */
  const downloadClose = (isDownloadFile) => {
    if (isDownloadFile) downloadPlayer.StopRecord()
    downloadPlayer && downloadPlayer.StopPullStream()
    downloadPlayer && downloadPlayer.Stop()
    clearTimeout(downloadTimer)
    downloadPlayer.CancelRecord()
    downloadPlayer = null
  }

  const setPanoAR = () => {
    player && player.SetPanoAR(props.panoAR)
  }

  /**
   * @method playFF 倍速
   */
  const playFF = (speed) => {
    player && player.SetSpeed(speed)
  }

  /**
   * @method fastForward 快进
   * @param { Number } second 快进秒数
   */
  const fastForward = (second = 15) => {
    if (!player) return
    const playTime = player.GetCurrentPlayedTime()
    const seekTime = playTime + second
    debugger
    player.SetSeekTime(seekTime)
  }

  /**
   * @method fastRewind 快退
   * @param { Number } second 快退秒数
   */
  const fastRewind = (second = 15) => {
    if (!player) return
    const playTime = player.GetCurrentPlayedTime()
    const seekTime = playTime - second
    player.SetSeekTime(seekTime)
  }

  /**
   * @method visionControl 图像调节
   * @param { Number } b 亮度。默认64；范围0-128
   * @param { Number } c 对比度。默认64；范围0-128
   * @param { Number } s 饱和度。默认64；范围0-128
   * @param { Number } t 色调。默认64；范围0-128
   */
  const visionControl = (b = 64, c = 64, s = 64, t = 64) => {
    player && player.SetColor(b, c, s, t)
  }

  /**
   * @method digitalZoom 电子放大区域设置
   * @param { Object } srcRect 放大区域 { left. right, top, bottom}
   */
  const digitalZoom = (srcRect) => {
    player && player.SetDisplayRegion(srcRect)
  }

  /**
   * @method watermarkOverlay 水印叠加
   * @param { Array } osdList 水印信息列表
   */
  const watermarkOverlay = (osdList) => {
    const WatermarkInfo = {}
    WatermarkInfo.osdCount = osdList.length
    WatermarkInfo.osdList = osdList
    player && player.SetYUVOSDInfoEx(WatermarkInfo)
  }

  const cPlusVisibleDecCallBack = (nPort, pBufY, pBufU, pBufV, nSize, pFrameInfo) => {
    if (nPort == playerPort) {
      player && player.SetFrameData(nPort, pBufY, pBufU, pBufV, nSize, pFrameInfo)
    }
    if (nPort == downloadPlayerPort) {
      downloadPlayer &&
        downloadPlayer.SetFrameData(nPort, pBufY, pBufU, pBufV, nSize, pFrameInfo, 0)
    }
    if (nPort == talkPort) {
      talkPlayer &&
        talkPlayer.SetFrameData(nPort, pBufY, pBufU, pBufV, nSize, pFrameInfo, volume, true)
    }
  }

  const cDigitalSignCallBack = (nPort, nFrameID, bSuccess) => {
    if (nPort == playerPort) {
      player && player.SetDecryptionResult(nPort, nFrameID, bSuccess)
    }
    if (nPort == downloadPlayerPort) {
      downloadPlayer && downloadPlayer.SetDecryptionResult(nPort, nFrameID, bSuccess)
    }
  }

  const cExtraDrawDataCallBack = (nPort, nDataType, pDrawData, nDataLen) => {
    if (nPort == playerPort) {
      player && player.setIVSData(nPort, nDataType, pDrawData, nDataLen)
    }
    if (nPort == downloadPlayerPort) {
      downloadPlayer && downloadPlayer.setIVSData(nPort, nDataType, pDrawData, nDataLen)
    }
  }

  const cExtraDrawDrawCallBack = (nPort) => {
    if (nPort == playerPort) {
      player && player.drawIVSData(nPort)
    }
    if (nPort == downloadPlayerPort) {
      downloadPlayer && downloadPlayer.drawIVSData(nPort)
    }
  }

  const cRecordDataCallBack = (nPort, pData, nDataLen, nOffset, pRecordFrameInfo) => {
    if (nPort == playerPort) {
      player && player.SetRecordData(nPort, pData, nDataLen, nOffset, pRecordFrameInfo)
    }
    if (nPort == downloadPlayerPort) {
      downloadPlayer &&
        downloadPlayer.SetRecordData(nPort, pData, nDataLen, nOffset, pRecordFrameInfo)
    }
  }

  const inputData = (handle, pData, nDataLength) => {
    if (handle == playerHandle) {
      player && player.InputDataEx(pData, nDataLength)
    }
    if (handle == downloadHandle) {
      downloadPlayer && downloadPlayer.InputDataEx(pData, nDataLength)
    }
    if (handle == talkHandle) {
      talkPlayer && talkPlayer.InputDataEx(pData, nDataLength)
    }
  }

  const stopPullStream = (handle) => {
    if (handle == playerHandle) {
      player && player.StopPullStream()
    }
    if (handle == downloadHandle) {
      downloadPlayer && downloadPlayer.StopPullStream()
    }
    if (handle == talkHandle) {
      talkPlayer && talkPlayer.StopPullStream()
    }
  }

  const streamFailedCallback = (handle, attach) => {
    if (handle == playerHandle) {
      player && player.StreamFailedCallback(attach)
    }
    if (handle == downloadHandle) {
      downloadPlayer && downloadPlayer.StreamFailedCallback(attach)
    }
    if (handle == talkHandle) {
      talkPlayer && talkPlayer.StreamFailedCallback(attach)
    }
  }

  const streamDisconnectCallback = (handle) => {
    if (handle == playerHandle) {
      player && player.StreamDisconnectCallback()
    }
    if (handle == downloadHandle) {
      downloadPlayer && downloadPlayer.StreamDisconnectCallback()
    }
    if (handle == talkHandle) {
      talkPlayer && talkPlayer.StreamDisconnectCallback()
    }
  }

  const streamFinishCallback = (handle) => {
    if (handle == playerHandle) {
      player && player.StreamFinishCallback()
    }
    if (handle == downloadHandle) {
      downloadPlayer && downloadPlayer.StreamFinishCallback()
    }
    if (handle == talkHandle) {
      talkPlayer && talkPlayer.StreamFinishCallback()
    }
  }

  const streamRedirectCallback = (handle, attach) => {
    if (handle == playerHandle) {
      player && player.StreamRedirectCallback(attach)
    }
    if (handle == downloadHandle) {
      downloadPlayer && downloadPlayer.StreamRedirectCallback(attach)
    }
    if (handle == talkHandle) {
      talkPlayer && talkPlayer.StreamRedirectCallback(attach)
    }
  }

  const cIVSDrawDataCallBack = (nPort, buf, type, len, reallen) => {
    //外部TODO,比如360AR中的设备位置信息通过此回调返回，由上层写到设备
    if (handle == playerHandle) {
      player && player.SetIVSDrawData(nPort, buf, type, len, reallen)
    }
    if (handle == downloadHandle) {
      downloadPlayer && downloadPlayer.SetIVSDrawData(nPort, buf, type, len, reallen)
    }
    if (handle == talkHandle) {
      talkPlayer && talkPlayer.SetIVSDrawData(nPort, buf, type, len, reallen)
    }
  }
  onMounted(() => {
    const ivsCanvs = playRefs[`ivsCan-${props.id}`]

    ivsCanvs.addEventListener('mousedown', function () {
      !!props.panoAR && player && player.OnMouseDown()
    })

    ivsCanvs.addEventListener('mousemove', function (event) {
      !!props.panoAR && player && player.OnMouseMove(event.clientX, event.clientY)
    })

    ivsCanvs.addEventListener('mouseup', function () {
      !!props.panoAR && player && player.OnMouseUp()
    })

    ivsCanvs.addEventListener('wheel', function (event) {
      !!props.panoAR && player && player.OnMouseWheel(event.wheelDelta)
    })
  })

  defineExpose({
    play,
    talk,
    talkMute,
    talkEnabled,
    record,
    screenshot,
    close,
    setAudioVolume,
    setTalkVolume,
    pause,
    start,
    playFF,
    download,
    downloadPause,
    downloadStart,
    downloadClose,
    openIVS,
    closeIVS,
    setPanoAR,
    cPlusVisibleDecCallBack,
    cDigitalSignCallBack,
    cExtraDrawDataCallBack,
    cExtraDrawDrawCallBack,
    cRecordDataCallBack,
    inputData,
    stopPullStream,
    streamFailedCallback,
    streamDisconnectCallback,
    streamFinishCallback,
    streamRedirectCallback,
    cIVSDrawDataCallBack,
    getScreenshot,
    fastForward,
    fastRewind,
    visionControl,
    digitalZoom,
    watermarkOverlay,
  })
</script>

<style lang="less" scoped>
  .video-player-context {
    width: 100%;
    height: 100%;
    position: relative;
    .video-player-canvas {
      position: absolute;
      top: 0;
    }
    canvas {
      width: 100%;
      height: 100%;
      object-fit: fill;
    }
    video {
      width: 100%;
      height: 100%;
      top: 0;
      object-fit: fill;
    }
    img {
      width: 479px;
      height: 178px;
      display: block;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    .diy-device-id {
      position: absolute;
      background: #fff;
      padding: 16px 16px 0 16px;
      width: 300px;
      left: calc(50% - 150px);
      top: calc(50% - 64px);
      border-radius: 4px;
    }
  }
</style>
